import {Prefab, resources} from 'cc';
import {GameManager} from "db://assets/scripts/game/GameManager";
import {PoolManager} from "db://assets/scripts/common/PoolManager";
import {CSVManager} from "db://assets/scripts/common/CSVManager";
import {StageConverter} from "db://assets/scripts/data/converter/StageConverter";
import {CSVPaths} from "db://assets/scripts/common/CSVPaths";
import {SkillConverter} from "db://assets/scripts/data/converter/SkillConverter";
import {ModelPaths} from "db://assets/scripts/common/ModelPaths";
import {EffectPaths} from "db://assets/scripts/common/EffectPaths";

/**
 * 游戏预加载代理
 */
export class GamePreloadProxy {
    /**
     * 已经预加载的敌人技能
     * string：技能ID
     * number：该技能出现了几次
     */
    private monsterSkills: Map<string, number> = new Map<string, number>();

    /**
     * 代理对象
     */
    private proxy: GameManager;

    constructor(proxy: GameManager) {
        this.proxy = proxy;

        // 初始化
        this.init();
    }

    /**
     * 初始化
     */
    private init() {

    }

    /**
     * 每层进入前预加载该层所需的敌人技能
     *
     * @param tableName 关卡表名
     * @param callback 回调
     */
    public preloadMonsterSkill(tableName: string, callback?: Function) {
        // 关卡信息
        let stageCSV = CSVManager.getInstance().getTable(CSVPaths[tableName]);
        let stages = StageConverter.convertFromCSV(stageCSV);

        // 获取所有敌人信息
        stages = stages.filter(state => state.id.startsWith("2"));
        // 当没有敌人时
        if (stages.length === 0) {
            return;
        }

        // 等待预加载的技能
        let loadSkillIds: string[] = [];

        // 获取敌人技能列表
        let skillIds: string[] = [];
        stages.forEach(stage => {
            skillIds = skillIds.concat(stage.skill === "" ? [] : stage.skill.split("#"));
        });
        // 当没有技能需要加载时
        if (skillIds.length === 0) {
            return;
        }

        skillIds.forEach(id => {
            // 当技能列表中没有这个技能时
            if (!this.monsterSkills.has(id)) {
                // 需要加载
                loadSkillIds.push(id);
                // 记录技能出现次数
                this.monsterSkills.set(id, 1);
            } else {
                // 在需要加载的技能列表中一共出现了一次
                let arr = skillIds.filter((itemId: string) => {
                    return itemId === id;
                })

                if (arr.length > this.monsterSkills.get(id)) {
                    loadSkillIds.push(id);
                    this.monsterSkills.set(id, this.monsterSkills.get(id) + 1);
                }
            }
        });
        // 没有需要加载的技能
        if (loadSkillIds.length === 0) {
            return;
        }

        // 加载技能特效
        let monsterSkillCSV = CSVManager.getInstance().getTable(CSVPaths.monsterSkill);
        let monsterSkills = SkillConverter.convertFromCSV(monsterSkillCSV);
        loadSkillIds.forEach(id => {
            // 找到需要加载的技能
            let skill = monsterSkills.find(skill => skill.id === id);
            // 加载技能特效
            resources.load(EffectPaths[skill.resourceName], Prefab, (err: Error, prefab: Prefab) => {
                if (err) {
                    console.log(err);
                    return;
                }
                let node = PoolManager.getInstance().getNode(prefab, this.proxy.node);
                node.setWorldPosition(this.proxy.node.worldPosition.x, 30, this.proxy.node.worldPosition.z);
            });
        });

        // 执行回调
        callback && callback();
    }

    /**
     * 预加载弓箭特效
     *
     * @param size 预生成的节点数量
     */
    public preloadArrowEffects(size: number) {
        resources.loadDir("prefab/effect/arrow", Prefab, (err, prefabs: Prefab[]) => {
            if (err) {
                console.log(err);
                return;
            }

            prefabs.forEach(prefab => PoolManager.getInstance().preloadPool(prefab, size));
        });
    }

    /**
     * 预加载箭模型
     *
     * @param arrowName 箭的模型名称
     * @param size 预生成的节点数量
     */
    public preloadArrow(arrowName: string, size: number) {
        resources.load(ModelPaths[arrowName], Prefab, (err: Error, prefab: Prefab) => {
            PoolManager.getInstance().preloadPool(prefab, size);
        });
    }
}